/* randomgraphreader.cpp
Desc.: Graph reader class implementation that gives edges in random order
Auth.: Ashwin Lall
Start: March 19, 2014
*/ 

#include "randomgraphreader.h"
#include <fstream>
#include <stdlib.h>
#include <time.h>

using namespace std;

RandomGraphReader::RandomGraphReader(string filename, int seed)
{
    string line;
    int node1, node2;
    int c = 1;
    ifstream file;
    map<int, int> label;
    srand(seed);

    _curr = 0;

    // count the number of edges
    file.open(filename.c_str());
    if (!file.is_open()) return;  // bail out if not a valid file
    _numedges = 0;
    while(getline(file, line))
    {
	if (line[0] != '#')
	    _numedges++;
    }
    file.close();

    // allocate space
    _edges = new int[2 * _numedges];
    
    // fail if we cannot allocate so much space
    if (_edges == NULL)
	return;

    // read in the edges 
    file.open(filename.c_str());
    while (getline(file, line))
    {
	if (line[0] != '#')
	{
	    sscanf(line.c_str(), "%d %d", &node1, &node2);

	    // re-lable nodes so that they are 1,2,3,....
	    if (label.count(node1) == 0)
	    {
		label[node1] = c;
		c++;
	    }
	    if (label.count(node2) == 0)
	    {
		label[node2] = c;
		c++;
	    }

	    _edges[_curr] = label[node1];
	    _edges[_curr+1] = label[node2];
	    _curr += 2;
	}
    }
    file.close();

    // permute the edges randomly
    for (int i = 0; i < _numedges - 1; ++i)
    {
	int j = i + rand() % (_numedges - i);

	// swap positions i and j
	int temp = _edges[2 * i];
	_edges[2 * i] = _edges[2 * j];
	_edges[2 * j] = temp;
	temp = _edges[2 * i + 1];
        _edges[2 * i + 1] = _edges[2 * j + 1];
        _edges[2 * j + 1] = temp;
    }

    _curr = 0;
}

bool RandomGraphReader::nextEdge(int &node1, int &node2)
{
    if (_curr >= 2 * _numedges)
	return false;
    
    node1 = _edges[_curr];
    node2 = _edges[_curr+1];
    _curr += 2;

    return true;
}

RandomGraphReader::~RandomGraphReader()
{
    if (_edges != NULL)
	delete[] _edges;
}
